#include "ievent.h"

#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>

#include "itick.h"

#include "epollreactor.h"

namespace net {

EpollReactor::EpollReactor() {
	fd_ = epoll_create(MAX_EPOLL_SIZE);
}

EpollReactor::~EpollReactor() {
	if(fd_ != -1) {
		close(fd_);
		fd_ = -1;
	}
}

TickManager* EpollReactor::GetTickManager() {
    return &tickManager_;
}
   
void EpollReactor::Stop() {
}

void EpollReactor::Dispatch() {
	while(1) {
        uint32_t tick = tickManager_.GetTick();
		int ret = epoll_wait(fd_, events_, MAX_EPOLL_SIZE, tick);
		if(ret == -1) {		
			if(errno == EINTR) {
				continue;	
			}
		}
		else if(ret == 0) { 
            tickManager_.OnTick();
		}
		else {				
			OnEvent(ret);	
		}
	}
}

void EpollReactor::OnEvent(uint32_t count) {
	for(uint32_t i = 0; i < count; i++) {
		IEvent* event = (IEvent*)events_[i].data.ptr;
		event->OnEvent(events_[i].events);
	}
}

void EpollReactor::RemoveEvent(IEvent* event) {
}

void EpollReactor::AddEvent(IEvent* event, uint32_t type) {
	epoll_event e = {0};
	e.events = EPOLLET | EPOLLRDHUP;
	if(type & Read) {
		e.events |= EPOLLIN;
	}
	if(type & Write) {
		e.events |= EPOLLOUT;
	}
	e.data.ptr = (void*)event;

	int ret = epoll_ctl(fd_, EPOLL_CTL_ADD, event->GetFd(), &e);
    if (ret == -1) {
	    char* error = strerror(errno);
    }
	assert(ret != -1);
}

}

